<!-- components/TkiQrCode/TkiQrCode.vue -->
<template>
	<view
		class="qr-container"
		:style="{ width: size + 'px', height: size + 'px' }"
	>
		<canvas
			class="qr-canvas"
			:canvas-id="canvasId"
			:id="canvasId"
			:style="{ width: size + 'px', height: size + 'px' }"
		></canvas>
	</view>
</template>

<script>
import QRCode from './sdk/code.js';

export default {
	name: 'TkiQrCode',
	props: {
		value: {
			type: String,
			required: true,
		},
		size: {
			type: Number,
			default: 200,
		},
		canvasId: {
			type: String,
			default: 'tki-qrcode-canvas',
		},
		margin: {
			type: Number,
			default: 1,
		},
		background: {
			type: String,
			default: '#FFFFFF',
		},
		foreground: {
			type: String,
			default: '#000000',
		},
		autoMake: {
			type: Boolean,
			default: true,
		},
		logo: {
			type: String,
			default: '',
		},
		logoSize: {
			type: Number,
			default: 0.2,
		},
		logoBackgroundColor: {
			type: String,
			default: null,
		},
		logoCornerRadius: {
			type: Number,
			default: 4,
		},
	},

	data() {
		return {
			dpr: 1,
		};
	},

	mounted() {
		// 获取设备像素比
		const systemInfo = uni.getSystemInfoSync();
		this.dpr = systemInfo.pixelRatio || 1;

		if (this.autoMake) {
			// 延迟执行确保canvas已经渲染
			this.$nextTick(() => {
				setTimeout(() => {
					this.make();
				}, 100);
			});
		}
	},

	methods: {
		async make() {
			if (!this.value) return;

			try {
				// 生成二维码矩阵
				const qr = new QRCode(0, 'M');
				qr.addData(this.value);
				qr.make();

				// 获取canvas上下文
				const canvas = this.getCanvasContext();

				// 清空画布
				this.clearCanvas(canvas);

				// 绘制背景
				this.drawBackground(canvas);

				// 绘制二维码
				this.drawQRCode(canvas, qr);

				// 绘制logo
				if (this.logo) {
					await this.drawLogo(canvas);
				}

				// 渲染到屏幕
				this.renderCanvas(canvas, () => {
					this.$emit('made');
					this.save();
				});
			} catch (error) {
				console.error('生成二维码失败:', error);
				this.$emit('error', error);
			}
		},

		getCanvasContext() {
			return uni.createCanvasContext(this.canvasId, this);
		},

		clearCanvas(ctx) {
			ctx.clearRect(0, 0, this.size, this.size);
		},

		drawBackground(ctx) {
			ctx.setFillStyle(this.background);
			ctx.fillRect(0, 0, this.size, this.size);
		},

		drawQRCode(ctx, qr) {
			const moduleCount = qr.getModuleCount();
			const cellSize = this.size / moduleCount;

			// 考虑边距
			const marginPx = this.margin * 4;
			const contentSize = this.size - 2 * marginPx;
			const actualCellSize = contentSize / moduleCount;

			ctx.setFillStyle(this.foreground);

			for (let row = 0; row < moduleCount; row++) {
				for (let col = 0; col < moduleCount; col++) {
					if (qr.isDark(row, col)) {
						const x = marginPx + col * actualCellSize;
						const y = marginPx + row * actualCellSize;
						ctx.fillRect(x, y, actualCellSize, actualCellSize);
					}
				}
			}
		},

		async drawLogo(ctx) {
			console.log('开始绘制Logo...');
			try {
				let logoPath = this.logo;

				// 如果是网络图片，先下载
				if (this.logo.startsWith('http') || this.logo.startsWith('https')) {
					const [downloadResult] = await uni.downloadFile({
						url: this.logo,
					});
					logoPath = downloadResult.tempFilePath;
				}

				// 计算logo位置和尺寸
				const marginPx = this.margin * 4;
				const contentSize = this.size - 2 * marginPx;
				const logoWidth = contentSize * this.logoSize;
				const logoHeight = contentSize * this.logoSize;
				const logoX = marginPx + (contentSize - logoWidth) / 2;
				const logoY = marginPx + (contentSize - logoHeight) / 2;

				// 绘制logo背景（如果有设置）
				if (this.logoBackgroundColor) {
					ctx.setFillStyle(this.logoBackgroundColor);
					this.drawRoundedRect(
						ctx,
						logoX,
						logoY,
						logoWidth,
						logoHeight,
						this.logoCornerRadius
					);
					ctx.fill();
				}

				// 绘制logo图片
				ctx.drawImage(logoPath, logoX, logoY, logoWidth, logoHeight);
			} catch (error) {
				console.error('绘制Logo失败:', error);
				this.$emit('logoError', error);
			}
		},

		drawRoundedRect(ctx, x, y, width, height, radius) {
			radius = Math.min(radius, width / 2, height / 2);
			ctx.beginPath();
			ctx.moveTo(x + radius, y);
			ctx.lineTo(x + width - radius, y);
			ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
			ctx.lineTo(x + width, y + height - radius);
			ctx.quadraticCurveTo(
				x + width,
				y + height,
				x + width - radius,
				y + height
			);
			ctx.lineTo(x + radius, y + height);
			ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
			ctx.lineTo(x, y + radius);
			ctx.quadraticCurveTo(x, y, x + radius, y);
			ctx.closePath();
		},

		renderCanvas(ctx, callback) {
			ctx.draw(false, () => {
				if (callback && typeof callback === 'function') {
					callback();
				}
			});
		},

		save() {
			// #ifdef H5
			uni.canvasToTempFilePath(
				{
					canvasId: this.canvasId,
					success: res => {
						this.$emit('result', res.tempFilePath);
					},
					fail: error => {
						console.error('导出二维码图片失败:', error);
						this.$emit('result', null);
					},
				},
				this
			);
			// #endif

			// #ifndef H5
			uni.canvasToTempFilePath({
				canvasId: this.canvasId,
				success: res => {
					this.$emit('result', res.tempFilePath);
				},
				fail: error => {
					console.error('导出二维码图片失败:', error);
					this.$emit('result', null);
				},
			});
			// #endif
		},

		// 重新生成二维码
		reMake() {
			this.make();
		},
	},
};
</script>

<style scoped>
.qr-container {
	position: relative;
	display: inline-block;
}

.qr-canvas {
	width: 100%;
	height: 100%;
}
</style>
